#ifndef _ANN_DISTANCE_FIELD_H_
#define _ANN_DISTANCE_FIELD_H_

#include <vector>
#include <algorithm>
#include <valarray>
#include <iterator>

#include <boost/shared_ptr.hpp>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

#include <Geex/third_party/tsANN/include/ANN/ANN.h>

#include "common/polytope.h"
#include "common/field_grid_2.h" // for local frame

namespace Field_packing
{
	using namespace Packing_common;
	
	class ANN_distance_field_2
	{
	public:
		typedef CGAL::Exact_predicates_inexact_constructions_kernel::Point_2 Point_2;
		typedef CGAL::Exact_predicates_inexact_constructions_kernel::Line_2	Line_2;
		typedef CGAL::Exact_predicates_inexact_constructions_kernel::Vector_2	Vector_2;
		typedef CGAL::Exact_predicates_inexact_constructions_kernel::Aff_transformation_2	Transformation_2;

	public:
		ANN_distance_field_2(const std::vector< Packing_polygon* >& polygon_set, unsigned int sample_rate);
		~ANN_distance_field_2(); //{ annClose(); }
		// query the nearest point on polygon id from p, and return the squared nearest distance
		double nearest_point_at(const Point_2& p, size_t polygon_id, Point_2& nearest_pnt) const;
		// update the coordinate system of a polygon
		void update_distance_field(size_t polygon_id, const Transformation_2& transformation)
		{
			local_frames[polygon_id].transform(transformation);
		}

	private:
		std::vector< boost::shared_ptr<ANNkd_tree> > kdtrees; // kd-trees formed by the sampling points on polygons

		//typedef boost::shared_ptr<std::iterator_traits<ANNpointArray>::value_type> Shared_ptr;
		std::vector< ANNpointArray > point_pool; // contain all the sampling points
		std::vector< Local_frame_2 > local_frames; // local coordinate system of each polygon
		size_t nb_polygons;
	};
}

#endif